home *** CD-ROM | disk | FTP | other *** search
- /* << ACE >>
-
- -- Amiga BASIC Compiler --
-
- ** Parser: file functions **
- ** Copyright (C) 1998 David Benn
- **
- ** This program is free software; you can redistribute it and/or
- ** modify it under the terms of the GNU General Public License
- ** as published by the Free Software Foundation; either version 2
- ** of the License, or (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program; if not, write to the Free Software
- ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
- Author: David J Benn
- Date: 26th October-30th November, 1st-13th December 1991,
- 14th,20th-27th January 1992,
- 2nd-17th, 21st-29th February 1992,
- 1st,13th,14th,22nd,23rd March 1992,
- 21st,22nd April 1992,
- 2nd,3rd,11th,15th,16th May 1992,
- 7th,8th,9th,11th,13th,14th,28th,29th,30th June 1992,
- 2nd-8th,14th-19th,26th-29th July 1992,
- 1st-3rd,7th,8th,9th August 1992,
- 6th,7th December 1992,
- 4th,5th,6th January 1993,
- 12th,14th,15th February 1993,
- 1st March 1993,
- 9th,17th,18th May 1993,
- 15th December 1993,
- 2nd January 1994,
- 11th March 1995,
- 10th March 1996
- */
-
- #include "acedef.h"
- #include <string.h>
-
- /* locals */
- static char *frame_ptr[] = {"(a4)", "(a5)"};
-
- /* externals */
- extern int lev;
- extern int sym;
- extern int obj;
- extern int typ;
- extern BOOL end_of_source;
- extern SYM *curr_item;
- extern char id[MAXIDSIZE];
- extern char tempstrname[80];
-
- /* functions */
- void open_a_file (void)
- {
- /* OPEN mode,[#]filenumber,filespec */
-
- check_for_event ();
-
- insymbol ();
- if (expr () != stringtype)
- _error (4); /* mode = I, O or A */
- else
- {
- if (sym != comma)
- _error (16);
- else
- {
- insymbol ();
- if (sym == hash)
- insymbol (); /* # filenumber */
- if (make_integer (expr ()) == shorttype)
- make_long (); /* 1..255 */
- if (sym != comma)
- _error (16);
- else
- {
- insymbol ();
- if (expr () != stringtype)
- _error (4); /* filespec */
- else
- {
- /* pop arguments */
- gen ("move.l", "(sp)+", "a1"); /* address of filespec */
- gen ("move.l", "(sp)+", "d0"); /* filenumber */
- gen ("move.l", "(sp)+", "a0"); /* address of mode string */
-
- gen ("jsr", "_openfile", " ");
- enter_XREF ("_openfile");
- enter_XREF ("_DOSBase");
- }
- }
- }
- }
- }
-
- void close_a_file (void)
- {
- /* CLOSE [#]filenumber[,[#]filenumber..] */
-
- check_for_event ();
-
- do
- {
- insymbol ();
- if (sym == hash)
- insymbol ();
- if (make_integer (expr ()) == shorttype)
- make_long (); /* filenumber = 1..255 */
-
- gen ("move.l", "(sp)+", "d0");
- gen ("jsr", "_closefile", " ");
- }
- while (sym == comma);
-
- enter_XREF ("_closefile");
- enter_XREF ("_DOSBase");
- }
-
- void line_input (void)
- {
- char addrbuf[40];
- SYM *storage;
-
- /* LINE INPUT [;][prompt-string;]string-variable
- LINE INPUT# filenumber;string-variable
-
- Note: only the latter is currently implemented.
- */
-
- check_for_event ();
-
- insymbol ();
-
- if (sym != hash)
- _error (44);
- else
- {
- insymbol ();
-
- if (make_integer (expr ()) == shorttype)
- make_long (); /* filenumber = 1..255 */
-
- if (sym != comma)
- _error (16);
- else
- {
- insymbol ();
-
- if (sym == ident && obj == variable)
- {
- /* if string variable/array doesn't exist, create a simple variable */
- if (!exist (id, variable) && !exist (id, array))
- {
- /* allocate a simple string variable */
- enter (id, typ, obj, 0);
- enter_DATA("_nullstring:", "dc.b 0");
- gen ("pea", "_nullstring", " ");
- assign_to_string_variable (curr_item, MAXSTRLEN);
- }
-
- storage = curr_item;
-
- /* is it a string variable or array? */
- if (storage->type != stringtype)
- _error (4);
- else
- {
- /* get address of string pointed to by variable/array element */
- itoa (-1 * storage->address, addrbuf, 10);
- strcat (addrbuf, frame_ptr[lev]);
-
- /* pass filenumber (d0) and string address (a0) to function */
- if (storage->object == array)
- {
- point_to_array (storage, addrbuf);
- gen ("move.l", addrbuf, "a0");
- gen ("adda.l", "d7", "a0");
- }
- else
- gen ("move.l", addrbuf, "a0"); /* string address */
-
- gen ("move.l", "(sp)+", "d0"); /* filenumber */
-
- /* call _line_input */
- gen ("jsr", "_line_input", " ");
- enter_XREF ("_line_input");
-
- insymbol ();
- if (sym == lparen && storage->object != array)
- _error (71); /* undeclared array */
- }
- }
- else
- _error (19); /* variable (or array) expected */
- }
- }
- }
-
- void write_to_file (void)
- {
- int wtype;
-
- /* WRITE #filenumber,expression-list */
-
- check_for_event ();
-
- insymbol ();
-
- if (sym != hash)
- _error (44);
- else
- {
- insymbol ();
-
- if (make_integer (expr ()) == shorttype)
- make_long (); /* filenumber = 1..255 */
-
- gen ("move.l", "(sp)+", "_seq_filenumber");
-
- if (sym != comma)
- _error (16);
- else
- {
- /* get expressions */
- do
- {
- insymbol ();
- wtype = expr ();
-
- switch (wtype)
- {
- case undefined:
- _error (0); /* expression expected */
- break;
-
- case shorttype:
- gen ("move.w", "(sp)+", "d1");
- gen ("move.l", "_seq_filenumber", "d0");
- gen ("jsr", "_writeshort", " ");
- enter_XREF ("_writeshort");
- break;
-
- case longtype:
- gen ("move.l", "(sp)+", "d1");
- gen ("move.l", "_seq_filenumber", "d0");
- gen ("jsr", "_writelong", " ");
- enter_XREF ("_writelong");
- break;
-
- case singletype:
- gen ("move.l", "(sp)+", "d1");
- gen ("move.l", "_seq_filenumber", "d0");
- gen ("jsr", "_writesingle", " ");
- enter_XREF ("_writesingle");
- enter_XREF ("_MathBase");
- break;
-
- case stringtype:
- gen ("move.l", "_seq_filenumber", "d0");
- gen ("jsr", "_writequote", " ");
- gen ("move.l", "(sp)+", "a0");
- gen ("move.l", "_seq_filenumber", "d0");
- gen ("jsr", "_writestring", " ");
- gen ("move.l", "_seq_filenumber", "d0");
- gen ("jsr", "_writequote", " ");
- enter_XREF ("_writequote");
- enter_XREF ("_writestring");
- break;
- }
-
- /* need a delimiter? */
- if (sym == comma)
- {
- gen ("move.l", "_seq_filenumber", "d0");
- gen ("jsr", "_writecomma", " ");
- enter_XREF ("_writecomma");
- }
-
- }
- while (sym == comma);
-
- /* write LF to mark EOLN */
- gen ("move.l", "_seq_filenumber", "d0");
- gen ("jsr", "_write_eoln", " ");
- enter_XREF ("_write_eoln");
-
- enter_XREF ("_DOSBase");
- enter_BSS ("_seq_filenumber:", "ds.l 1");
- }
- }
- }
-
- void gen_writecode (int code)
- {
- /* write special character sequence to a file */
-
- check_for_event ();
-
- gen ("move.l", "_seq_filenumber", "d0");
-
- switch (code)
- {
- /* LF */
- case LF_CODE:
- gen ("jsr", "_write_eoln", " ");
- enter_XREF ("_write_eoln");
- break;
- /* TAB */
- case TAB_CODE:
- gen ("jsr", "_writeTAB", " ");
- enter_XREF ("_writeTAB");
- break;
- /* SPACE */
- case SPACE_CODE:
- gen ("jsr", "_writeSPC", " ");
- enter_XREF ("_writeSPC");
- break;
- }
- }
-
- void print_to_file (void)
- {
- int exprtype, arguments = 0;
-
- /* PRINT #filenumber,expression-list */
-
- check_for_event ();
-
- insymbol ();
-
- if (make_integer (expr ()) == shorttype)
- make_long (); /* filenumber 1..255 */
-
- gen ("move.l", "(sp)+", "_seq_filenumber");
- enter_BSS ("_seq_filenumber:", "ds.l 1");
-
- if (sym != comma)
- _error (16);
- else
- {
- do
- {
- if (sym != ident && !strfunc () && !numfunc () && !factorfunc () &&
- obj != constant)
- insymbol (); /* ident/func/literal after a space or as first parameter */
-
- /* end of line, multi-statement, ";", "," ELSE or comment
- after "PRINT #filenumber," ? -> don't proceed to expr! */
-
- if ((sym == endofline) || (sym == colon) || (sym == apostrophe) ||
- (sym == semicolon) || (sym == comma) || (sym == elsesym) ||
- (end_of_source))
- {
- if (sym == comma)
- gen_writecode (TAB_CODE);
- else if ((arguments == 0) && (sym != semicolon))
- gen_writecode (LF_CODE); /* "PRINT #filenumber," with no args */
-
- if (sym != colon && sym != elsesym)
- insymbol (); /* leave colon for multi-statement
- in statement() or leave ELSE for if_statement() */
- return;
- }
-
- /* get an expression */
- exprtype = expr ();
-
- if (exprtype == undefined)
- {
- _error (0);
- return;
- } /* illegal syms? */
-
- /* pass filenumber to write routine */
- if (exprtype == stringtype)
- gen ("move.l", "_seq_filenumber", "d0");
- else
- gen ("move.l", "_seq_filenumber", "d1");
-
- switch (exprtype)
- {
- case shorttype:
- gen ("move.w", "(sp)+", "d0");
- gen ("jsr", "_fprintshort", " ");
- enter_XREF ("_fprintshort");
- break;
-
- case longtype:
- gen ("move.l", "(sp)+", "d0");
- gen ("jsr", "_fprintlong", " ");
- enter_XREF ("_fprintlong");
- break;
-
- case singletype:
- gen ("move.l", "(sp)+", "d0");
- gen ("jsr", "_fprintsingle", " ");
- enter_XREF ("_fprintsingle");
- enter_XREF ("_MathBase");
- break;
-
- case stringtype:
- gen ("movea.l", "(sp)+", "a0");
- gen ("jsr", "_writestring", " ");
- enter_XREF ("_writestring");
- break;
- }
-
- if (exprtype != stringtype)
- gen_writecode (SPACE_CODE); /* trailing space for any number */
-
- arguments++;
-
- if (sym == comma)
- gen_writecode (TAB_CODE);
-
- }
- while ((sym == comma) || (sym == semicolon) || (sym == ident) ||
- strfunc () || numfunc () || factorfunc () || obj == constant);
-
- /* no comma or semicolon at end of PRINT# -> LF */
- gen_writecode (LF_CODE);
- }
- }
-
- void input_from_file (void)
- {
- char addrbuf[80];
- SYM *storage;
-
- /* INPUT #filenumber,variable-list */
-
- check_for_event ();
-
- insymbol ();
-
- if (make_integer (expr ()) == shorttype)
- make_long (); /* filenumber 1..255 */
-
- gen ("move.l", "(sp)+", "_seq_filenumber");
- enter_BSS ("_seq_filenumber:", "ds.l 1");
-
- if (sym != comma)
- _error (16);
- else
- {
- do
- {
- /* allocate variable storage, call _input* and store value in variable */
-
- insymbol ();
-
- if ((sym == ident) && (obj == variable))
- {
- if ((!exist (id, obj)) && (!exist (id, array)))
- enter (id, typ, obj, 0); /* allocate storage for a simple variable */
-
- storage = curr_item;
-
- itoa (-1 * storage->address, addrbuf, 10);
- strcat (addrbuf, frame_ptr[lev]);
-
- /* ALL data types need a temporary string pointer in a1 */
- make_temp_string ();
- gen ("lea", tempstrname, "a0"); /* unique temp holder */
-
- /* when storing an input value into an array element, must save
- value (d0) first, since array index calculation may be corrupted
- if index has to be coerced from ffp to short.
- */
-
- /* pass file number */
- gen ("move.l", "_seq_filenumber", "d0");
-
- switch (storage->type)
- {
- case shorttype:
- gen ("jsr", "_finputshort", " ");
-
- if (storage->object == variable)
- {
- if ((storage->shared) && (lev == ONE))
- {
- gen ("move.l", addrbuf, "a0"); /* abs address of store */
- gen ("move.w", "d0", "(a0)");
- }
- else
- /* ordinary variable */
- gen ("move.w", "d0", addrbuf);
- }
- else if (storage->object == array)
- {
- gen ("move.w", "d0", "_short_input_temp");
- point_to_array (storage, addrbuf);
- gen ("move.w", "_short_input_temp", "0(a2,d7.L)");
- enter_BSS ("_short_input_temp:", "ds.w 1");
- }
-
- enter_XREF ("_finputshort");
- break;
-
- case longtype:
- gen ("jsr", "_finputlong", " ");
-
- if (storage->object == variable)
- {
- if ((storage->shared) && (lev == ONE))
- {
- gen ("move.l", addrbuf, "a0"); /* abs address of store */
- gen ("move.l", "d0", "(a0)");
- }
- else
- /* ordinary variable */
- gen ("move.l", "d0", addrbuf);
- }
- else if (storage->object == array)
- {
- gen ("move.l", "d0", "_long_input_temp");
- point_to_array (storage, addrbuf);
- gen ("move.l", "_long_input_temp", "0(a2,d7.L)");
- enter_BSS ("_long_input_temp:", "ds.l 1");
- }
-
- enter_XREF ("_finputlong");
- break;
-
- case singletype:
- gen ("jsr", "_finputsingle", " ");
-
- if (storage->object == variable)
- {
- if ((storage->shared) && (lev == ONE))
- {
- gen ("move.l", addrbuf, "a0"); /* abs address of store */
- gen ("move.l", "d0", "(a0)");
- }
- else
- /* ordinary variable */
- gen ("move.l", "d0", addrbuf);
- }
- else if (storage->object == array)
- {
- gen ("move.l", "d0", "_long_input_temp");
- point_to_array (storage, addrbuf);
- gen ("move.l", "_long_input_temp", "0(a2,d7.L)");
- enter_BSS ("_long_input_temp:", "ds.l 1");
- }
-
- enter_XREF ("_finputsingle");
- enter_XREF ("_MathBase"); /* need math libs */
- enter_XREF ("_MathTransBase");
- break;
-
- case stringtype:
- gen ("jsr", "_finputstring", " ");
-
- gen ("move.l", "a0", "-(sp)");
-
- if (storage->object == variable)
- assign_to_string_variable (storage, MAXSTRLEN);
- else if (storage->object == array)
- {
- point_to_array (storage, addrbuf);
- assign_to_string_array (addrbuf);
- }
-
- enter_XREF ("_finputstring");
- break;
- }
- }
- else
- _error (19);
-
- insymbol ();
- if (sym == lparen && storage->object != array)
- _error (71); /* undeclared array */
- }
- while (sym == comma);
- }
- }
-
- void kill (void)
- {
- /* KILL <filespec> */
-
- check_for_event ();
-
- insymbol ();
- if (expr () != stringtype)
- _error (4);
- else
- {
- gen ("move.l", "(sp)+", "d1");
- gen ("jsr", "_kill", " ");
- enter_XREF ("_kill");
- }
- }
-
- void ace_rename (void)
- {
- /* NAME <filespec1> AS <filespec2> */
-
- check_for_event ();
-
- insymbol ();
- if (expr () != stringtype)
- _error (4);
- else
- {
- if (sym != assym)
- _error (72);
- else
- {
- insymbol ();
- if (expr () != stringtype)
- _error (4);
- else
- {
- gen ("move.l", "(sp)+", "d2"); /* <filespec2> */
- gen ("move.l", "(sp)+", "d1"); /* <filespec1> */
- gen ("jsr", "_ace_rename", " ");
- enter_XREF ("_ace_rename");
- }
- }
- }
- }
-
- void ace_chdir (void)
- {
- /* CHDIR <dirname> */
-
- check_for_event ();
-
- insymbol ();
-
- if (expr () != stringtype)
- _error (4);
- else
- {
- /* call code to change directory */
- gen ("move.l", "(sp)+", "d1"); /* dirname */
- gen ("jsr", "_ace_chdir", " ");
- enter_XREF ("_ace_chdir");
- }
- }
-
- void files (void)
- {
- /* FILES [TO <storefile>] [,<target>] */
-
- check_for_event ();
-
- insymbol ();
-
- /* storage file specified? */
- if (sym == tosym)
- {
- insymbol ();
- if (expr () != stringtype)
- _error (4);
- }
- else
- gen ("move.l", "#0", "-(sp)"); /* NULL for storage file name */
-
- /* target file or directory specified? */
- if (sym == comma)
- {
- insymbol ();
- if (expr () != stringtype)
- _error (4);
- }
- else
- gen ("move.l", "#0", "-(sp)"); /* NULL for target name */
-
- /* call _files routine */
- gen ("jsr", "_files", " ");
- gen ("addq", "#4", "sp");
- enter_XREF ("_files");
- }
-
- void push_struct_var_info (SYM * structVar)
- {
- char addrbuf[40], sizebuf[10];
-
- /*
- ** Push address held by structure variable.
- */
- sprintf (addrbuf, "%d%s", -1 * structVar->address, frame_ptr[lev]);
- if (structVar->shared && lev == ONE)
- {
- /*
- ** Shared structure variable.
- */
- gen ("movea.l", addrbuf, "a0"); /* struct variable address */
- gen ("move.l", "(a0)", "-(sp)"); /* start address of struct */
- }
- else
- /*
- ** Local structure variable,
- ** ie. in main program or SUB.
- */
- gen ("move.l", addrbuf, "-(sp)"); /* variable holds start address */
-
- /*
- ** Push size of structure in bytes.
- */
- sprintf (sizebuf, "#%d", structVar->other->size);
- gen ("move.l", sizebuf, "-(sp)");
- }
-
- void random_file_get (void)
- {
- /*
- ** Fill a structure from a random file.
- **
- ** SYNTAX: GET [#]fileNum, structVar [, recordNum]
- */
- SYM *structVar;
-
- check_for_event ();
-
- /*
- ** We already have the first symbol.
- ** Skip `#' if present.
- */
- if (sym == hash)
- insymbol ();
-
- /*
- ** Get the file number.
- */
- if (make_integer (expr ()) == shorttype)
- make_long (); /* filenumber 1..255 */
-
- if (sym != comma)
- _error (16);
- else
- {
- /*
- ** Structure variable address and size.
- */
- insymbol ();
- if (!exist (id, structure))
- _error (79);
- else
- {
- structVar = curr_item;
- push_struct_var_info (structVar);
-
- insymbol ();
- if (sym == comma)
- {
- /*
- ** Optional record number.
- */
- insymbol ();
- if (make_integer (expr ()) == shorttype)
- make_long (); /* record number >= 1 */
- }
- else
- /*
- ** Tell library function not to
- ** seek to a particular record
- ** before reading.
- */
- gen ("move.l", "#0", "-(sp)");
-
- /*
- ** Call function.
- */
- gen ("jsr", "_GetRecord", " ");
- gen ("add.l", "#16", "sp");
- enter_XREF ("_GetRecord");
- }
- }
- }
-
- void random_file_put (void)
- {
- /*
- ** Write a structure to a random file.
- **
- ** SYNTAX: PUT [#]fileNum, structVar [, recordNum]
- */
- SYM *structVar;
-
- check_for_event ();
-
- /*
- ** We already have the first symbol.
- ** Skip `#' if present.
- */
- if (sym == hash)
- insymbol ();
-
- /*
- ** Get the file number.
- */
- if (make_integer (expr ()) == shorttype)
- make_long (); /* filenumber 1..255 */
-
- if (sym != comma)
- _error (16);
- else
- {
- /*
- ** Structure variable address and size.
- */
- insymbol ();
- if (!exist (id, structure))
- _error (79);
- else
- {
- structVar = curr_item;
- push_struct_var_info (structVar);
-
- insymbol ();
- if (sym == comma)
- {
- /*
- ** Optional record number.
- */
- insymbol ();
- if (make_integer (expr ()) == shorttype)
- make_long (); /* record number >= 1 */
- }
- else
- /*
- ** Tell library function not to
- ** seek to a particular record
- ** before writing.
- */
- gen ("move.l", "#0", "-(sp)");
-
- /*
- ** Call function.
- */
- gen ("jsr", "_PutRecord", " ");
- gen ("add.l", "#16", "sp");
- enter_XREF ("_PutRecord");
- }
- }
- }
-